package controller

import (
	"net/http"
	"strconv"

	"soma-server/common"
	"soma-server/config"
	"soma-server/dto"
	modelSystem "soma-server/model/system"
	"soma-server/pkg/e"
	"soma-server/pkg/util"
	r "soma-server/response"
	serviceSystem "soma-server/service/system"
	"soma-server/vo"

	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"github.com/thoas/go-funk"
)

type IUserController interface {
	GetUserInfo(c *gin.Context)          // 获取当前登录用户信息
	GetUsers(c *gin.Context)             // 获取用户列表
	ChangePwd(c *gin.Context)            // 更新用户登录密码
	CreateUser(c *gin.Context)           // 创建用户
	UpdateUserById(c *gin.Context)       // 更新用户
	BatchDeleteUserByIds(c *gin.Context) // 批量删除用户
}

type UserController struct {
	UserService serviceSystem.IUserService
}

// 构造函数
func NewUserController() IUserController {
	userService := serviceSystem.NewUserService()
	userController := UserController{UserService: userService}
	return userController
}

// 获取当前登录用户信息
func (uc UserController) GetUserInfo(c *gin.Context) {
	user, err := uc.UserService.GetCurrentUser(c)
	if err != nil {
		common.Log.Errorf("获取当前用户信息失败: " + err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_GET_CURRENT_USER, nil, false)
		return
	}
	userInfoDto := dto.ToUserInfoDto(user)
	r.Response(c, http.StatusOK, e.SUCCESS_GET_CURRENT_USER, gin.H{
		"list": userInfoDto,
	}, true)
}

// 获取用户列表
func (uc UserController) GetUsers(c *gin.Context) {
	var req vo.UserListRequest
	// 参数绑定
	if err := c.ShouldBind(&req); err != nil {
		common.Log.Errorln(err.Error())
		r.Response(c, http.StatusBadRequest, e.BINDING_PARAMS, nil, false)
		return
	}
	// 参数校验
	if err := common.Validate.Struct(&req); err != nil {
		errStr := err.(validator.ValidationErrors)[0].Translate(common.Trans)
		common.Log.Errorln(errStr)
		r.Response(c, http.StatusBadRequest, e.INVALID_PARAMS, nil, false)
		return
	}

	// 获取
	users, total, err := uc.UserService.GetUsers(&req)
	if err != nil {
		common.Log.Errorln("获取用户列表失败: " + err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_GET_USER_LIST, nil, false)
		return
	}
	r.Response(c, http.StatusOK, e.SUCCESS_GET_USER_LIST, gin.H{
		"list":  dto.ToUsersDto(users),
		"total": total,
	}, true)
}

// 更新用户登录密码
func (uc UserController) ChangePwd(c *gin.Context) {
	var req vo.ChangePwdRequest

	// 参数绑定
	if err := c.ShouldBind(&req); err != nil {
		common.Log.Errorf(err.Error())
		r.Response(c, http.StatusBadRequest, e.BINDING_PARAMS, nil, false)
		return
	}
	// 参数校验
	if err := common.Validate.Struct(&req); err != nil {
		errStr := err.(validator.ValidationErrors)[0].Translate(common.Trans)
		common.Log.Errorln(errStr)
		r.Response(c, http.StatusBadRequest, e.INVALID_PARAMS, nil, false)
		return
	}

	// 前端传来的密码是rsa加密的,先解密
	// 密码通过RSA解密
	decodeOldPassword, err := util.RSADecrypt([]byte(req.OldPassword), config.Conf.System.RSAPrivateBytes)
	if err != nil {
		common.Log.Errorln(err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_AUTH_DECRYPT_PWD, nil, false)
		return
	}
	decodeNewPassword, err := util.RSADecrypt([]byte(req.NewPassword), config.Conf.System.RSAPrivateBytes)
	if err != nil {
		common.Log.Errorln(err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_AUTH_DECRYPT_PWD, nil, false)
		return
	}
	req.OldPassword = string(decodeOldPassword)
	req.NewPassword = string(decodeNewPassword)

	// 获取当前用户
	user, err := uc.UserService.GetCurrentUser(c)
	if err != nil {
		common.Log.Errorln(err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_GET_CURRENT_USER, nil, false)
		return
	}
	// 获取用户的真实正确密码
	correctPasswd := user.Password
	// 判断前端请求的密码是否等于真实密码
	err = util.ComparePasswd(correctPasswd, req.OldPassword)
	if err != nil {
		common.Log.Errorln("原密码有误")
		r.Response(c, http.StatusBadRequest, e.ERROR_USER_PWD_NOT_MATCH, nil, false)
		return
	}
	// 更新密码
	err = uc.UserService.ChangePwd(user.Username, util.GenPasswd(req.NewPassword))
	if err != nil {
		common.Log.Errorln("更新密码失败: " + err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_UPDATE_USER_PWD, nil, false)
		return
	}
	r.Response(c, http.StatusOK, e.SUCCESS_USER_UPDATE_PWD, nil, true)
}

// 创建用户
func (uc UserController) CreateUser(c *gin.Context) {
	var (
		req vo.CreateUserRequest
	)
	// 参数绑定
	if err := c.ShouldBind(&req); err != nil {
		common.Log.Errorln(err.Error())
		r.Response(c, http.StatusBadRequest, e.BINDING_PARAMS, nil, false)
		return
	}
	// 参数校验
	if err := common.Validate.Struct(&req); err != nil {
		errStr := err.(validator.ValidationErrors)[0].Translate(common.Trans)
		common.Log.Errorln(errStr)
		r.Response(c, http.StatusBadRequest, e.INVALID_PARAMS, nil, false)
		return
	}

	// 密码通过RSA解密
	// 密码不为空就解密
	if req.Password != "" {
		decodeData, err := util.RSADecrypt([]byte(req.Password), config.Conf.System.RSAPrivateBytes)
		if err != nil {
			common.Log.Errorln(err.Error())
			r.Response(c, http.StatusBadRequest, e.ERROR_AUTH_DECRYPT_PWD, nil, false)
			return
		}
		req.Password = string(decodeData)
		if len(req.Password) < 7 {
			common.Log.Errorln("密码长度至少为8位")
			r.Response(c, http.StatusBadRequest, e.ERROR_USER_PWD_NOT_ENOUGH_LENTH, nil, false)
			return
		}
	}

	// 当前用户角色排序最小值（最高等级角色）以及当前用户
	_, _, ctxUser, err := uc.UserService.GetCurrentUserMinRoleSort(c)
	if err != nil {
		common.Log.Errorln(err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_USER_GET_ROLE_ID_MIN, nil, false)
		return
	}

	// 获取前端传来的用户角色id
	reqRoleIds := req.RoleIds
	// 根据角色id获取角色
	rr := serviceSystem.NewRoleService()
	roles, err := rr.GetRolesByIds(reqRoleIds)
	if err != nil {
		common.Log.Errorln("根据角色ID获取角色信息失败: " + err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_GET_ROLE_BY_ROLEID, nil, false)
		return
	}

	// 判断nil，设置0值
	if req.Avatar == "" {
		newAvatar := new(string)
		req.Avatar = *newAvatar
	}
	if req.Nickname == "" {
		newNickname := new(string)
		req.Nickname = *newNickname
	}
	if req.Remark == "" {
		newRemark := new(string)
		req.Remark = *newRemark
	}

	user := modelSystem.User{
		Username: req.Username,
		Password: util.GenPasswd(req.Password),
		Mobile:   req.Mobile,
		Avatar:   &req.Avatar,
		Nickname: &req.Nickname,
		Remark:   &req.Remark,
		Status:   req.Status,
		Creator:  ctxUser.Username,
		Roles:    roles,
	}

	err = uc.UserService.CreateUser(&user)
	if err != nil {
		common.Log.Errorln("创建用户失败: " + err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_CREATE_USER, nil, false)
		return
	}
	r.Response(c, http.StatusOK, e.SUCCESS_CREATE_USER, nil, true)

}

// 更新用户
func (uc UserController) UpdateUserById(c *gin.Context) {
	var (
		req vo.CreateUserRequest
	)
	// 参数绑定
	if err := c.ShouldBind(&req); err != nil {
		common.Log.Errorln(err.Error())
		r.Response(c, http.StatusBadRequest, e.BINDING_PARAMS, nil, false)
		return
	}
	// 参数校验
	if err := common.Validate.Struct(&req); err != nil {
		errStr := err.(validator.ValidationErrors)[0].Translate(common.Trans)
		common.Log.Errorln(errStr)
		r.Response(c, http.StatusBadRequest, e.INVALID_PARAMS, nil, false)
		return
	}

	//获取path中的userId
	userId, _ := strconv.Atoi(c.Param("userId"))
	if userId <= 0 {
		common.Log.Errorln("用户ID不正确")
		r.Response(c, http.StatusBadRequest, e.ERROR_USER_ID_NOT_CORRECT, nil, false)
		return
	}

	// 根据path中的userId获取用户信息
	oldUser, err := uc.UserService.GetUserById(uint(userId))
	if err != nil {
		common.Log.Errorln("获取需要更新的用户信息失败: " + err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_GET_USER_INFO, nil, false)
		return
	}

	// 获取当前用户
	ctxUser, err := uc.UserService.GetCurrentUser(c)
	if err != nil {
		common.Log.Errorln(err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_GET_CURRENT_USER, nil, false)
		return
	}
	// 获取当前用户的所有角色
	currentRoles := ctxUser.Roles
	// 当前用户角色ID集合
	var currentRoleIds []uint
	for _, role := range currentRoles {
		currentRoleIds = append(currentRoleIds, role.ID)
	}

	// 获取前端传来的用户角色id
	reqRoleIds := req.RoleIds
	// 根据角色id获取角色
	rr := serviceSystem.NewRoleService()
	roles, err := rr.GetRolesByIds(reqRoleIds)
	if err != nil {
		common.Log.Errorln("根据角色ID获取角色信息失败: " + err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_GET_ROLE_BY_ROLEID, nil, false)
		return
	}

	user := modelSystem.User{
		Model:    oldUser.Model,
		Username: req.Username,
		Password: oldUser.Password,
		Mobile:   req.Mobile,
		Sex:      req.Sex,
		Avatar:   &req.Avatar,
		Nickname: &req.Nickname,
		Remark:   &req.Remark,
		Status:   req.Status,
		Creator:  ctxUser.Username,
		Roles:    roles,
	}
	// 判断是更新自己还是更新别人
	if userId == int(ctxUser.ID) {
		// 如果是更新自己
		// 不能禁用自己
		if req.Status == 2 {
			common.Log.Errorln("不能禁用自己")
			r.Response(c, http.StatusBadRequest, e.ERROR_USER_CANNOT_DISABLE_ITSELF, nil, false)
			return
		}
		// 不能更改自己的角色
		reqDiff, currentDiff := funk.Difference(req.RoleIds, currentRoleIds)
		if len(reqDiff.([]uint)) > 0 || len(currentDiff.([]uint)) > 0 {
			common.Log.Errorln("不能更改自己的角色")
			r.Response(c, http.StatusBadRequest, e.ERROR_USER_CANNOT_MODIFY_ITSELF, nil, false)
			return
		}

		// 不能更新自己的密码，只能在个人中心更新
		if req.Password != "" {
			common.Log.Errorln("请到个人中心更新自身密码")
			r.Response(c, http.StatusBadRequest, e.ERROR_MOVE_TO_USER_CENTER, nil, false)
			return
		}

		// 密码赋值
		user.Password = ctxUser.Password
	} else {
		// 如果是更新别人
		// 不能禁用 admin
		if req.Status == 2 && req.Username == "admin" {
			common.Log.Errorln("不能禁用 admin 用户")
			r.Response(c, http.StatusBadRequest, e.ERROR_CONNOT_DISABLED_ADMIN, nil, false)
			return
		}
		// 根据path中的userIdID获取用户角色排序最小值
		minRoleSorts, _, err := uc.UserService.GetUserMinRoleSortsByIds([]uint{uint(userId)})
		if err != nil {
			common.Log.Errorln("根据用户ID获取用户角色排序最小值失败")
			r.Response(c, http.StatusBadRequest, e.ERROR_USER_GET_ROLE_ID_MIN, nil, false)
			return
		}
		// 根据path中的userId获取用户
		 allUsers, err := uc.UserService.GetUserByIds([]uint{uint(userId)})
		if err != nil {
			common.Log.Errorln("根据用户ID获取用户角色排序最小值失败")
			r.Response(c, http.StatusBadRequest, e.ERROR_USER_GET_ROLE_ID_MIN, nil, false)
			return
		}

		// 不能更改 admin 用户
		if len(minRoleSorts) != 0 && minRoleSorts[0] == 1 {
			for _, user := range allUsers {
				copyUser := user
				if copyUser.Username == "admin" {
					common.Log.Errorln("不能更改 admin 用户")
					r.Response(c, http.StatusBadRequest, e.ERROR_CONNOT_MODIFY_ADMIN, nil, false)
					return
				}
			}
		}

		// 密码赋值
		if req.Password != "" {
			// 密码通过RSA解密
			decodeData, err := util.RSADecrypt([]byte(req.Password), config.Conf.System.RSAPrivateBytes)
			if err != nil {
				common.Log.Errorln(err.Error())
				r.Response(c, http.StatusBadRequest, e.ERROR_AUTH_DECRYPT_PWD, nil, false)
				return
			}
			req.Password = string(decodeData)
			user.Password = util.GenPasswd(req.Password)
		}
	}

	// 更新用户
	err = uc.UserService.UpdateUser(&user)
	if err != nil {
		common.Log.Errorln("更新用户失败: " + err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_UPDATE_USER, nil, false)
		return
	}
	r.Response(c, http.StatusOK, e.SUCCESS_UPDATE_USER, nil, true)

}

// 批量删除用户
func (uc UserController) BatchDeleteUserByIds(c *gin.Context) {
	var req vo.DeleteUserRequest
	// 参数绑定
	if err := c.ShouldBind(&req); err != nil {
		common.Log.Errorln(err.Error())
		r.Response(c, http.StatusBadRequest, e.BINDING_PARAMS, nil, false)
		return
	}
	// 参数校验
	if err := common.Validate.Struct(&req); err != nil {
		errStr := err.(validator.ValidationErrors)[0].Translate(common.Trans)
		common.Log.Errorln(errStr)
		r.Response(c, http.StatusBadRequest, e.INVALID_PARAMS, nil, false)
		return
	}

	// 前端传来的用户ID
	reqUserIds := req.UserIds
	// 根据用户ID获取用户角色排序最小值
	minSorts, _, err := uc.UserService.GetUserMinRoleSortsByIds(reqUserIds)
	if err != nil {
		common.Log.Errorln("根据用户ID获取用户角色排序最小值失败")
		r.Response(c, http.StatusBadRequest, e.ERROR_USER_GET_ROLE_ID_MIN, nil, false)
		return
	}
	// 根据用户ID获取所有用户
	 allUsers, err := uc.UserService.GetUserByIds(reqUserIds)
	if err != nil {
		common.Log.Errorln("根据用户ID获取用户角色排序最小值失败")
		r.Response(c, http.StatusBadRequest, e.ERROR_USER_GET_ROLE_ID_MIN, nil, false)
		return
	}

	// 当前用户角色排序最小值（最高等级角色）以及当前用户
	_, _, ctxUser, err := uc.UserService.GetCurrentUserMinRoleSort(c)
	if err != nil {
		common.Log.Errorln(err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_USER_GET_ROLE_ID_MIN, nil, false)
		return
	}

	// 不能删除自己
	if funk.Contains(reqUserIds, ctxUser.ID) {
		common.Log.Errorln("用户不能删除自己")
		r.Response(c, http.StatusBadRequest, e.ERROR_USER_DELETE_ITSELF, nil, false)
		return
	}

	if len(minSorts) !=0 &&  minSorts[0] == 1 {
		for _, user := range allUsers {
			copyUser := user
			if copyUser.Username == "admin" {
				common.Log.Errorln("不能删除 admin 用户")
			r.Response(c, http.StatusBadRequest, e.ERROR_CONNOT_DELETE_ADMIN, nil, false)
			return
			}
		}
	}

	err = uc.UserService.BatchDeleteUserByIds(reqUserIds)
	if err != nil {
		common.Log.Errorln("删除用户失败: " + err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_DELETE_USER_FAIL, nil, false)
		return
	}
	r.Response(c, http.StatusOK, e.SUCCESS_DELETE_USER, nil, true)

}
